package stream;


import domain.entity.OutstandingClass;
import domain.entity.Student;
import domain.enums.SpecialityEnum;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.averagingInt;
import static java.util.stream.Collectors.maxBy;

public class StreamTest {

    public static void main(String[] args) {
        streamOfCollectTest();

        streamOfFilterTest();

        streamMapTest();

        streamFlatMapTest();

        streamMaxAndMinTest();

        streamCountTest();

        streamReduceTest();

        transformToValue();

        streamPartitioningByTest();

        streamGroupTest();


        streamJoinTest();
    }

    /**
     * 字符串拼接
     */
    private static void streamJoinTest() {
        List<Student> students = new ArrayList<>(3);
        students.add(new Student("路飞", 22, 175));
        students.add(new Student("红发", 40, 180));
        students.add(new Student("白胡子", 50, 185));

        String names = students.stream()
                .map(Student::getName).collect(Collectors.joining(",","[","]"));
        System.out.println(names);
    }

    /**
     * 对指定数据按照指定元素进行分组
     */
    private static void streamGroupTest() {
        List<Student> students = new ArrayList<>();
        students.add(new Student("路飞", 23, 175,Arrays.asList(SpecialityEnum.MOVIES,SpecialityEnum.SING)));
        students.add(new Student("红发", 40, 180,Arrays.asList(SpecialityEnum.MOVIES,SpecialityEnum.READ)));
        students.add(new Student("白胡子", 50, 185,Arrays.asList(SpecialityEnum.MOVIES,SpecialityEnum.SING)));
        //省略List<student> students的初始化
        Map<SpecialityEnum, List<Student>> listMap =
                students.stream().collect(
                        Collectors.groupingBy(student -> student.getSpecialities().get(0)));
        System.out.println(listMap);
    }


    /**
     * 对指定数据按照是或者不是进行分组，返回一个map,map中包含两个键值对，两个键分别为true,和false
     */
    private static void streamPartitioningByTest() {
        List<Student> students = new ArrayList<>();
        students.add(new Student("路飞", 23, 175,Arrays.asList(SpecialityEnum.MOVIES,SpecialityEnum.SING)));
        students.add(new Student("红发", 40, 180,Arrays.asList(SpecialityEnum.MOVIES,SpecialityEnum.READ)));
        students.add(new Student("白胡子", 50, 185,Arrays.asList(SpecialityEnum.MOVIES,SpecialityEnum.SING)));


        //省略List<student> students的初始化
        Map<Boolean, List<Student>> listMap = students.stream().collect(
                Collectors.partitioningBy(student -> student.getSpecialities().
                        contains(SpecialityEnum.SING)));
        System.out.println(listMap);
    }

    private static void transformToValue() {
        List<Student> students1 = new ArrayList<>(3);
        students1.add(new Student("路飞", 23, 175));
        students1.add(new Student("红发", 40, 180));
        students1.add(new Student("白胡子", 50, 185));

        OutstandingClass ostClass1 = new OutstandingClass("一班", students1);
        //复制students1，并移除一个学生
        List<Student> students2 = new ArrayList<>(students1);
        students2.remove(1);
        OutstandingClass ostClass2 = new OutstandingClass("二班", students2);
        //将ostClass1、ostClass2转换为Stream
        Stream<OutstandingClass> classStream = Stream.of(ostClass1, ostClass2);
        OutstandingClass outstandingClass = biggestGroup(classStream);
        System.out.println("人数最多的班级是：" + outstandingClass.getName());

        System.out.println("一班平均年龄是：" + averageNumberOfStudent(students1));
    }

    /**
     * 获取人数最多的班级
     */
    private static OutstandingClass biggestGroup(Stream<OutstandingClass> outstandingClasses) {
        return outstandingClasses.collect(maxBy(comparing(ostClass -> ostClass.getStudents().size())))
                .orElseGet(OutstandingClass::new);
    }

    /**
     * 计算平均年龄
     */
    private static double averageNumberOfStudent(List<Student> students) {
        return students.stream().collect(averagingInt(Student::getAge));
    }

    /**
     * 合并流的元素并产生单个值。
     */
    private static void streamReduceTest() {
        // reduce 方法中的第一参数表示结果的初始值
        Integer reduce = Stream.of(1, 2, 3, 4).reduce(0, (acc, x) -> acc+ x);
        System.out.println(reduce);
    }

    /**
     * 获取流中的元素的个数
     */
    private static void streamCountTest() {
        List<Student> students = new ArrayList<>(3);
        students.add(new Student("路飞", 22, 175));
        students.add(new Student("红发", 40, 180));
        students.add(new Student("白胡子", 50, 185));

        long count = students.stream().filter(s1 -> s1.getAge() < 45).count();
        System.out.println("年龄小于45岁的人数是：" + count);
    }

    /**
     * 获取流中的最大以及最小的数据
     */
    private static void streamMaxAndMinTest() {
        List<Student> students = new ArrayList<>(3);
        students.add(new Student("路飞", 22, 175));
        students.add(new Student("红发", 40, 180));
        students.add(new Student("白胡子", 50, 185));

        Optional<Student> max = students.stream()
                .max(comparing(stu -> stu.getAge()));
        Optional<Student> min = students.stream()
                .min(comparing(stu -> stu.getAge()));
        //判断是否有值
        if (max.isPresent()) {
            System.out.println(max.get());
        }
        if (min.isPresent()) {
            System.out.println(min.get());
        }
    }

    /**
     * 将两个流中的数据整合到一起
     */
    private static void streamFlatMapTest() {
        List<Student> students = new ArrayList<>(3);
        students.add(new Student("路飞", 22, 175));
        students.add(new Student("红发", 40, 180));
        students.add(new Student("白胡子", 50, 185));

        List<Student> studentList = Stream.of(students,
                Arrays.asList(new Student("艾斯", 25, 183),
                        new Student("雷利", 48, 176)))
                .flatMap(students1 -> students1.stream()).collect(Collectors.toList());
        System.out.println(studentList);
    }

    /**
     * 对流进行转换，并整理成集合
     */
    private static void streamMapTest() {
        List<Student> students = new ArrayList<>(3);
        students.add(new Student("路飞", 22, 175));
        students.add(new Student("红发", 40, 180));
        students.add(new Student("白胡子", 50, 185));

        List<String> names = students.stream().map(student -> student.getName())
                .collect(Collectors.toList());
        System.out.println(names);
    }

    /**
     * 对指定流进行过滤，过滤出符合条件的数据
     */
    private static void streamOfFilterTest() {
        List<Student> students = new ArrayList<>(3);
        students.add(new Student("路飞", 22, 175));
        students.add(new Student("红发", 40, 180));
        students.add(new Student("白胡子", 50, 185));

        List<Student> list = students.stream()
                .filter(stu -> stu.getStature() < 180)
                .collect(Collectors.toList());
        System.out.println(list);
    }


    /**
     * 将零散数据收集为对应的集合
     */
    private static void streamOfCollectTest() {
        List<Student> studentList = Stream.of(
                new Student("路飞", 22, 175),
                new Student("红发", 40, 180),
                new Student("白胡子", 50, 185)).collect(Collectors.toList());
        System.out.println(studentList);
    }
}
